#include "function_object.h"
#include "mytools.h"
#include <algorithm>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <vector>

using namespace std;

void PrintInt::operator()(int i) const { std::cout << i << " "; }

template <int value> void add(int &elem) { elem += value; }

AddValue::AddValue(int v) : value(v) {}

void AddValue::operator()(int &elem) const { elem += value; }

// 定义一个函数对象
void function_object() {
  print_title("Function Object");
  vector<int> v = {1, 2, 3, 4, 5};
  // 对 vector 中的每个元素调用 PrintInt 函数对象
  for_each(v.begin(), v.end(), PrintInt());
  cout << endl;
}

void template_function_object() {
  print_title("Template Function Object");
  int x = 5;
  add<10>(x);
  std::cout << x << std::endl;
}

void total_function_object() {
  print_title("Total Function Object");
  list<int> l;
  for (int i = 0; i < 9; ++i) {
    l.push_back(i);
  }

  PRINT_ELEMENTS(l, "initialized:           ");

  for_each(l.begin(), l.end(), AddValue(10));

  PRINT_ELEMENTS(l, "after adding 10:       ");

  for_each(l.begin(), l.end(), AddValue(*l.begin()));

  PRINT_ELEMENTS(l, "after adding first:    ");
}

// 预定义的函数对象
void predefined_function_object() {
  print_title("Predefined Function Object");
  deque<int> coll = {1, 2, 3, 5, 7, 11, 13, 17, 19};
  PRINT_ELEMENTS(coll, "initialized:              ");
  transform(coll.cbegin(), coll.cend(), coll.begin(), negate<int>());
  PRINT_ELEMENTS(coll, "after negating:           ");
  transform(coll.cbegin(), coll.cend(), coll.cbegin(), coll.begin(),
            multiplies<int>());
  PRINT_ELEMENTS(coll, "after squared:            ");
}
